/**
 * 
 */
package com.iss.card.view.collent;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.Adapter;
import android.widget.LinearLayout;

import com.iss.card.R;
import com.iss.card.cache.BitmapConfig;
import com.iss.card.cache.ImageDataManager;
import com.iss.card.common.ApplicationManager;
import com.iss.card.model.MarkedProductDetailInfo;
import com.iss.card.view.overrideview.IOnItemSelectedListener;
import com.iss.card.view.overrideview.ScrollViewRefresh.IOnScrollChangedListener;
import com.iss.card.view.store.RecycleableImageView;

/**
 * @author dtdh
 * 
 */
public class MarkedProductListViewContainer extends LinearLayout implements
		IOnScrollChangedListener {
	private final static String TAG = MarkedProductListViewContainer.class
			.getSimpleName();
	private final static int BUFFERED_MAX_VIEW = 2;
	private Context mContext = null;
	private LinearLayout[] mSubContainer;
	private int mColumnWidth = 0;
	private int mColumnSpace = 0;
	private int mColumnNum = 0;
	private int mMaxRowInOnePage = 5;
	private IOnItemSelectedListener mOnItemSelectedListener = null;
	private int mHeight = 0;
	private MarkedProductListAdapter mAdapter = null;
	private List<ViewHolder> mViews = new ArrayList<ViewHolder>();
	private int mCurrentRow = 0;
	private int mTotalRow = 0;

	/**
	 * @param context
	 */
	public MarkedProductListViewContainer(Context context) {
		super(context);
		mContext = context;
	}

	/**
	 * @param context
	 * @param attrs
	 */
	public MarkedProductListViewContainer(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
	}

	/**
	 * set this container's height.
	 * 
	 * @param h
	 *            height for this container.
	 */
	public void setHeight(int h) {
		mHeight = h;
		LinearLayout.LayoutParams parameter = new LinearLayout.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		this.setLayoutParams(parameter);
		Log.d(TAG, "setHeight: h=" + mHeight);
	}

	public void setOnItemSelectedListener(IOnItemSelectedListener l) {
		mOnItemSelectedListener = l;
	}

	public void removeOnItemSelectedListener() {
		mOnItemSelectedListener = null;
	}

	public void setAdapter(MarkedProductListAdapter ad) {
		if (mAdapter != null && mObserver != null) {
			mAdapter.unregisterDataSetObserver(mObserver);
		}
		mAdapter = ad;
		mAdapter.registerDataSetObserver(mObserver);
		mColumnNum = mAdapter.getColumnCount();
		init();
	}

	public Adapter getAdapter() {
		return mAdapter;
	}

	public void onScrollChanged(int l, int t, int oldl, int oldt) {
		final int curRow = findRowByVerticalCoordinate(t);
		Log.d(TAG, "onScrollChanged: " + l + ", " + t + ", oldl=" + oldl
				+ ", oldt=" + oldt + ", row=" + curRow + ", preRow="
				+ mCurrentRow);
		if (t > oldt) { // down.
			if (curRow != mCurrentRow) {
				setViewVisible(mCurrentRow + mMaxRowInOnePage, true);
				setViewVisible(mCurrentRow - BUFFERED_MAX_VIEW, false);
				mCurrentRow = curRow;				
			}
		} else { // up.
			if (curRow != mCurrentRow) {
				
				if(curRow + mMaxRowInOnePage >= mTotalRow){
					mCurrentRow = curRow;
					setViewVisible(mCurrentRow - 1, true);
					
				}else{
					mCurrentRow = curRow;
					setViewVisible(mCurrentRow - 1, true);
					setViewVisible(mCurrentRow + mMaxRowInOnePage, false);
				}
				
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.view.View#onDetachedFromWindow()
	 */
	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		if (mAdapter != null) {
			mAdapter.unregisterDataSetObserver(mObserver);
		}
		clearAllSubviews();
		mViews.clear();
		removeOnItemSelectedListener();
	}

	private DataSetObserver mObserver = new DataSetObserver() {

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.database.DataSetObserver#onChanged()
		 */
		@Override
		public void onChanged() {
			Log.d(TAG, "onChanged");
			super.onChanged();
			clearAllSubviews();
			final int size = mAdapter.getCount();
			mTotalRow = size/mColumnNum;
			if(size%mColumnNum !=0){
				mTotalRow +=1;
			}
			for (int i = 0; i < size; ++i) {
				final int column = i % mColumnNum;
				final int row = i / mColumnNum;
				final int pos = i;
				final View v = mAdapter.getView(column, row, null, null);
				v.setOnClickListener(new OnClickListener() {

					@Override
					public void onClick(View v) {
						if (mOnItemSelectedListener != null) {
							mOnItemSelectedListener.OnItemSelected(
									MarkedProductListViewContainer.this, v,
									pos, mAdapter.getRowItem(column, row));
						}
					}
				});
				addSubView(v, column, row);
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.database.DataSetObserver#onInvalidated()
		 */
		@Override
		public void onInvalidated() {
			Log.d(TAG, "onInvalidated");
			super.onInvalidated();
		}

	};

	private void init() {
		this.setOrientation(LinearLayout.HORIZONTAL);
		mColumnSpace = mContext.getResources().getDimensionPixelSize(
				R.dimen.DIM_MARGIN_FOR_COLUMN_SPACE);
		mColumnWidth = ApplicationManager.getScreenWidth(mContext) / mColumnNum;
		mSubContainer = new LinearLayout[mColumnNum];
		for (int i = 0; i < mSubContainer.length; ++i) {
			LinearLayout l = new LinearLayout(mContext);
			LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
					mColumnWidth, LayoutParams.WRAP_CONTENT);
			l.setPadding(mColumnSpace, 0, mColumnSpace, mColumnSpace);
			l.setOrientation(LinearLayout.VERTICAL);
			l.setLayoutParams(lp);
			mSubContainer[i] = l;
			this.addView(l);
		}
	}

	private void clearAllSubviews() {
		for (int i = 0; i < mSubContainer.length; ++i) {
			mSubContainer[i].removeAllViews();
		}
	}

	private void addSubView(View v, int column, int row) {
		
		LayoutParams layoutParams = new LayoutParams(mColumnWidth,
				LayoutParams.WRAP_CONTENT);
		layoutParams.bottomMargin = mColumnSpace;
		v.setLayoutParams(layoutParams);
		MarkedProductDetailInfo item = (MarkedProductDetailInfo) mAdapter
				.getRowItem(column, row);
		Log.d(TAG,
				"addSubView: v=" + v + ", (" + column + ", " + row + ")"
						+ ", w=" + item.getProductPicW() + ", h="
						+ item.getProductPicH());
		final int h = item.getProductPicH() * mColumnWidth
				/ item.getProductPicW();
		RecycleableImageView img = (RecycleableImageView) ((LinearLayout) v)
				.getChildAt(0);
		img.setLayoutParams(new LinearLayout.LayoutParams(mColumnWidth, h));
		mSubContainer[column].addView(v);
		mSubContainer[column].measure(0, 0);
		
		if (row <= mMaxRowInOnePage) {
			ImageDataManager.instance().loadBitmap(
					item.getProductPicUrl(),
					img,
					new BitmapConfig(mColumnWidth, (item.getProductPicH()
							* mColumnWidth / item.getProductPicW())));
		}
		
		ViewHolder holder = new ViewHolder();
		holder.mView = v;
		holder.mColumn = column;
		holder.mRow = row;
		holder.mHeight = mSubContainer[column].getMeasuredHeight();
		mViews.add(holder);
		Log.d(TAG, "addSubView: h=" + mSubContainer[column].getMeasuredHeight()
				+ ", vh=" + v.getMeasuredHeight() + ", column=" + column
				+ ", row=" + row);
	}

	private void setViewVisible(int row, boolean isVisible) {
		Log.d(TAG, "setViewVisible: row=" + row + ", isVisible=" + isVisible);
		final int max = mSubContainer[0].getChildCount() - 1;
		row = row < 0 ? 0 : row;
		row = row > max ? max : row;
		for (int i = 0; i < mColumnNum; ++i) {
			if (mSubContainer[i].getChildCount() - 1 < row) {
				return;
			}

			setViewVisible(mAdapter.getView(i, row,
					mSubContainer[i].getChildAt(row), null),
					mAdapter.getRowItem(i, row), isVisible);
		}
	}

	private void setViewVisible(View v, Object item, boolean isVisible) {
		Log.d(TAG, "setViewVisible: v=" + v + ", isVisible=" + isVisible);
		RecycleableImageView img = ((RecycleableImageView) ((LinearLayout) v)
				.getChildAt(0));
		Log.d("kitexy", "is show ===> " + img.isShown());
		if (!isVisible) {
			img.recycleBitmap();
		} else {
			MarkedProductDetailInfo info = (MarkedProductDetailInfo) item;
			ImageDataManager.instance().loadBitmap(
					(String) img.getTag(),
					img,
					new BitmapConfig(mColumnWidth, (info.getProductPicH()
							* mColumnWidth / info.getProductPicW())));
		}
	}

	private int fetchMaxHeightInRow(int row) {
		int max = mViews.get(row * mColumnNum + 0).mHeight;
		for (int i = 1; i < mColumnNum; ++i) {
			int tmp = mViews.get(row * mColumnNum + i).mHeight;
			if (tmp > max) {
				max = tmp;
			}
		}
		return max;
	}

	/**
	 * find the row by vertical coordinate. now we just use the first column to
	 * search. 0 will be return as default.
	 * 
	 * @param y
	 *            vertical coordinate.
	 * @return the row in first column.
	 */
	private int findRowByVerticalCoordinate(int y) {
		int curRow = mCurrentRow;
		curRow = curRow < 0 ? 0 : curRow;
		final int curY = mViews.get(curRow).mHeight;
		Log.d(TAG, "findRowByVerticalCoordinate: y=" + y + ", curY=" + curY);
		if (y > curY) {
			// the value is more than current Y, then search in positive
			// direction.
			int minY = curY;
			final int size = mViews.size();
			for (int i = curRow + mColumnNum; i < size; i += mColumnNum) {
				Log.d(TAG, "findRowByVerticalCoordinate: index=" + i
						+ ", maxY=" + mViews.get(i).mHeight);
				if (y <= mViews.get(i).mHeight && y > minY) {
					return i / mColumnNum;
				}
				minY = mViews.get(i).mHeight;
			}
		} else if (y < curY) {
			// the value is less than current Y, then search in negative
			// direction.
			int maxY = curY;
			for (int i = curRow - mColumnNum; i >= 0; i -= mColumnNum) {
				if (y > mViews.get(i).mHeight && y <= maxY) {
					return i / mColumnNum;
				}
				maxY = mViews.get(i).mHeight;
			}
		} else {
			return curRow;
		}
		return 0;
	}

	private final class ViewHolder {
		public View mView;
		public int mColumn;
		public int mRow;
		public int mHeight;
	}
}
